package com.osdp.common.sercurity.filter;

import com.osdp.common.constant.CommonConstant;
import com.osdp.common.http.Result;
import com.osdp.common.sercurity.domain.Principal;
import com.osdp.common.sercurity.service.ITokenIdentifyService;
import com.osdp.common.base.JWTInfo;
import com.osdp.common.sercurity.service.impl.DefaultAuthenticateService;
import com.osdp.common.util.HttpUtil;
import com.osdp.common.util.MessageUtil;
import com.osdp.common.util.TokenHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.CollectionUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@Slf4j
public class TokenVerifyFilter extends BasicAuthenticationFilter {
    @Autowired
    private DefaultAuthenticateService authenticateService;

    @Autowired
    private ITokenIdentifyService tokenIdentifyService;

    public TokenVerifyFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    public TokenVerifyFilter(AuthenticationManager authenticationManager,
                             ITokenIdentifyService tokenIdentifyService,
                             DefaultAuthenticateService authenticateService){
        this(authenticationManager);
        this.tokenIdentifyService = tokenIdentifyService;
        this.authenticateService = authenticateService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (!isFeignRequest(request)) {
            String token = TokenHolder.getToken();
            if(token == null){
                log.error("token为空");
                HttpUtil.serverError(response, Result.fail(4015, MessageUtil.getMessage(10020)).toJson());
                return;
            }
            Principal principal = null;
            try {
                principal = tokenIdentifyService.checkAndGetPrincipal(token);
            }catch (Exception e){
                HttpUtil.serverError(response, Result.fail(4015, MessageUtil.getMessage(10021)).toJson());
            }

            UsernamePasswordAuthenticationToken authenticationToken = authenticateService.createUsernamePasswordAuthenticationToken(principal);
            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }
        chain.doFilter(request, response);
    }

    private boolean isFeignRequest(HttpServletRequest request){
        String isFeign = request.getHeader(CommonConstant.FEIGN_INVOKER);
        return StringUtils.equals(isFeign, "true");
    }

    /**
     * Noacos 命名空间
     */
    @Value("${spring.cloud.nacos.discovery.namespace}")
    private String localTenant;

    public boolean checkTenant(JWTInfo info){
        List<String> tenants = info.getTenants();
        if(CollectionUtils.isEmpty(tenants)){
            return false;
        }
        return StringUtils.isEmpty(localTenant) || tenants.contains(localTenant);
    }
}
